﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace CalculateModelClasses
{
    //点的信息

    public class Point
    {
        public double x, y, z;
        public Point(double a = 0, double b = 0, double c = 0)
        {
            x = a;
            y = b;
            z = c;
        }
        public bool unequal(Point one)
        {
            if (x != one.x || y != one.y || z != one.z) return true;
            else return false;
        }
    }

    //射线方向向量

    public class SpectVector
    {
        public double a, b, c;
        public SpectVector(Point origin, Point target)
        {
            a = target.x - origin.x;
            b = target.y - origin.y;
            c = target.z - origin.z;
        }
        public SpectVector(double x, double y, double z)
        {
            a = x; b = y; c = z;
        }
        public double Mag()
        {
            return Math.Sqrt(Math.Pow(a, 2) + Math.Pow(b, 2) + Math.Pow(c, 2));
        }

        //判断两个向量是否平行且同向
        public bool IsParallelAndSamedir(SpectVector linevector)
        {
            double angle = Math.Acos(linevector.a * a / Math.Sqrt(Math.Pow(a, 2) + Math.Pow(b, 2) + Math.Pow(c, 2)) + linevector.b * b / Math.Sqrt(Math.Pow(a, 2) + Math.Pow(b, 2) + Math.Pow(c, 2)) + linevector.c * c / Math.Sqrt(Math.Pow(a, 2) + Math.Pow(b, 2) + Math.Pow(c, 2)));
            angle = angle * 180 / Math.PI;
            if (angle <= 0.00000000001) return true;
            else return false;
        }

        //矢量叉乘运算
        public static SpectVector VectorCrossMultiply(SpectVector k, SpectVector l)
        {
            double x, y, z, x1, y1, z1, m;
            x1 = k.b * l.c - k.c * l.b;
            y1 = k.c * l.a - k.a * l.c;
            z1 = k.a * l.b - k.b * l.a;
            m = Math.Sqrt(Math.Pow(x1, 2) + Math.Pow(y1, 2) + Math.Pow(z1, 2));
            if (m == 0)
                x = y = z = 0;
            else
            {
                x = x1 / m;
                y = y1 / m;
                z = z1 / m;
            }
            SpectVector n = new SpectVector(x, y, z);
            return n;
        }

        //矢量点乘运算
        public static double VectorDotMultiply(SpectVector k, SpectVector l)
        {
            double m = k.a * l.a + k.b * l.b + k.c * l.c;
            return m;
        }

        //复数与矢量的点乘运算
        public static Efield VectorDotMultiply(Plural p, SpectVector l)
        {
            Plural X = new Plural(l.a * p.Re, l.a * p.Im);
            Plural Y = new Plural(l.b * p.Re, l.b * p.Im);
            Plural Z = new Plural(l.c * p.Re, l.c * p.Im);
            Efield e = new Efield(X, Y, Z);
            return e;
        }

        //复数向量与矢量的点乘运算
        public static Plural VectorDotMultiply(Efield e, SpectVector l)
        {
            Plural p = new Plural();
            p.Re = e.X.Re * l.a + e.Y.Re * l.b + e.Z.Re * l.c;
            p.Im = e.X.Im * l.a + e.Y.Im * l.b + e.Z.Im * l.c;
            return p;
        }

        //矢量与标量的点乘
        public static SpectVector VectorDotMultiply(double d, SpectVector l)
        {
            SpectVector s = new SpectVector(l.a * d, l.b * d, l.c * d);
            return s;
        }

        //矢量夹角计算
        public static double VectorPhase(SpectVector k, SpectVector l)
        {
            double m, n;
            m = VectorDotMultiply(k, l);
            double temp = Math.Sqrt(Math.Pow(k.a, 2) + Math.Pow(k.b, 2) + Math.Pow(k.c, 2)) * Math.Sqrt(Math.Pow(l.a, 2) + Math.Pow(l.b, 2) + Math.Pow(l.c, 2));
            if (temp == 0)
                n = 0;
            else
                n = m / temp;
            double phase = Math.Acos(n) / Math.PI * 180;
            return phase;
        }

    }

    //三角面的信息

    public class Face
    {
        public Point X, Y, Z;
        public double conductivity, permittivity;
        public Face(Point x, Point y, Point z, double c = 0, double p = 0)
        {
            X = x;
            Y = y;
            Z = z;
            conductivity = c;
            permittivity = p;
        }
        public SpectVector GetVeticalVector()
        {
            double[] ab = { Y.x - X.x, Y.y - X.y, Y.z - X.z };
            double[] ac = { Z.x - X.x, Z.y - X.y, Z.z - X.z };
            double[] acXab = { ac[1] * ab[2] - ac[2] * ab[1], -ac[0] * ab[2] + ac[2] * ab[0], ac[0] * ab[1] - ac[1] * ab[0] };
            SpectVector temp = new SpectVector(acXab[0], acXab[1], acXab[2]);
            return temp;
        }//获得三角面的法向量

        public static List<Point> CommonPoints(Face a, Face b)
        {
            List<Point> points = new List<Point>();
            if (a.X == b.X || a.X == b.Y || a.X == b.Z) points.Add(a.X);
            if (a.Y == b.X || a.Y == b.Y || a.Y == b.Z) points.Add(a.Y);
            if (a.Z == b.X || a.Z == b.Y || a.Z == b.Z) points.Add(a.Z);
            return points;
        }


    }

    //射线信息

    public class RayInfo
    {
        public Point origin;
        public SpectVector RayVector;
        public RayInfo(Point one, SpectVector vector)
        {
            origin = one;
            RayVector = vector;
        }
    }

    //记录射线与地形交点、与源点距离、所在面

    public class Pfd
    {
        public Point crosspoint;
        public Face correspond;
        public double distance;
        public Pfd(Point a, Face b, double c = 0)
        {
            crosspoint = a;
            correspond = b;
            distance = c;
        }

    }

    //绕射转换矩阵，求逆等操作

    public class Matrix
    {
        double[,] m;
        int length, width;
        public Matrix(int l, int w)
        {
            length = l; width = w;
            m = new double[l, w];
        }
        public double this[int x, int y]
        {
            get
            {
                return m[x, y];
            }
            set
            {
                m[x, y] = value;
            }
        }
        public int Length
        {
            get { return length; }
        }
        public int Width
        {
            get { return width; }
        }
        public static Matrix operator *(Matrix a, Matrix b)
        {
            //Console.WriteLine(" a:{0}X{1}  b:{2}X{3}", a.Length, a.Width, b.Length, b.Width);  

            if (a.Width != b.Length)
            {
                //  Console.WriteLine("error a:{0}X{1}  b:{2}X{3}", a.Length, a.Width, b.Length, b.Width);  
                return null;
            }
            Matrix c = new Matrix(a.Length, b.Width);
            for (int i = 0; i < c.Length; i++)
            {
                for (int j = 0; j < c.Width; j++)
                {
                    c[i, j] = 0;
                    for (int k = 0; k < a.Width; k++)
                    {
                        c[i, j] += a[i, k] * b[k, j];
                    }
                }
            }
            return c;
        }

        //三阶矩阵的行列式值
        public static double GetValue(Matrix A)
        {
            if (A.Length != A.Width) throw new Exception("非N阶矩阵");
            else if (A.Length != 3) throw new Exception("非三阶矩阵");
            else return (A[0, 0] * A[1, 1] * A[2, 2] + A[0, 1] * A[1, 2] * A[2, 0] + A[1, 0] * A[2, 1] * A[0, 2] - A[2, 0] * A[1, 1] * A[0, 2] - A[1, 0] * A[0, 1] * A[2, 2] - A[2, 1] * A[1, 2] * A[0, 0]);
        }
        //求逆  
        public static Matrix converse(Matrix m)
        {
            if (m.Length != m.Width)
            {
                return null;
            }
            if (GetValue(m) == 0) return null;
            //clone  
            Matrix a = new Matrix(m.Length, m.Width);
            for (int i = 0; i < a.Length; i++)
            {
                for (int j = 0; j < a.Width; j++)
                {
                    a[i, j] = m[i, j];
                }
            }
            Matrix c = new Matrix(a.Length, a.Width);
            for (int i = 0; i < a.Length; i++)
            {
                for (int j = 0; j < a.Width; j++)
                {
                    if (i == j) { c[i, j] = 1; }
                    else { c[i, j] = 0; }
                }
            }

            //i表示第几行，j表示第几列  
            for (int j = 0; j < a.Length; j++)
            {
                bool flag = false;
                for (int i = j; i < a.Length; i++)
                {
                    if (a[i, j] != 0)
                    {
                        flag = true;
                        double temp;
                        //交换i,j,两行  
                        if (i != j)
                        {
                            for (int k = 0; k < a.Length; k++)
                            {
                                temp = a[j, k];
                                a[j, k] = a[i, k];
                                a[i, k] = temp;

                                temp = c[j, k];
                                c[j, k] = c[i, k];
                                c[i, k] = temp;
                            }
                        }
                        //第j行标准化  
                        double d = a[j, j];
                        for (int k = 0; k < a.Length; k++)
                        {
                            a[j, k] = a[j, k] / d;
                            c[j, k] = c[j, k] / d;
                        }
                        //消去其他行的第j列  
                        d = a[j, j];
                        for (int k = 0; k < a.Length; k++)
                        {
                            if (k != j)
                            {
                                double t = a[k, j];
                                for (int n = 0; n < a.Length; n++)
                                {
                                    a[k, n] -= (t / d) * a[j, n];
                                    c[k, n] -= (t / d) * c[j, n];
                                }
                            }
                        }
                    }
                }
                if (!flag) return null;
            }
            return c;
        }
    }

    //记录节点信息

    public class Node
    {
        public string UAN;//发射机或接收机的UAN文件
        public int LayNum;//该节点所在的层数，发射机节点为1
        public int TxNum;//只有发射机节点有,若无置零
        public int RxNum;//只有到达接收点才有，如无置零
        public string NodeName;//只有发射机和接收机有名字
        public double frequence;//该点的发射频率
        public double FrequenceWidth;//频率带宽
        public Point Position;//该点的位置
        public bool IsEnd;//当射线反射或绕射三次后仍未到达接收机处时将该点设为终点
        public bool IsReceiver;//当到达接收机后设置为true，此时IsEnd也设为true
        public string PointStyle;//该点的类型，有发射点，反射点，绕射点，终点，接收点
        public double distance;//该点与其上一点的距离
        public Efield TotalE;  // 该点的总电场值，可用于结果显示和计算下一点的电场值
        public Plural EX;    //   X轴方向电场结果显示
        public Plural EY;    //  Y轴方向电场结果显示
        public Plural EZ;    //  Z轴方向电场结果显示
        public Plural Power;   // 功率结果显示
        public Face ReflectionFace;//反射点时的反射面，其他点时为null
        public Point Linea;//绕射点时的棱点
        public Point Lineb;//绕射点时的棱点
        public RayInfo RayIn;  //入射射线
        //public RayInfo RayOut;  //出射射线
        public List<Face> DiffractionFaces;//绕射点所在的两个面，非绕射点为空
        public List<Node> ChildNodes;//该点后的子节点


        //构造后进行赋值
        public Node()
        {
            ChildNodes = new List<Node>();
        }
        public Node(Node t)
        {
            UAN = t.UAN;
            LayNum = t.LayNum;
            TxNum = t.TxNum;
            RxNum = t.RxNum;
            NodeName = t.NodeName;
            frequence = t.frequence;
            FrequenceWidth = t.FrequenceWidth;
            Position = t.Position;
            IsEnd = t.IsEnd;
            IsReceiver = t.IsReceiver;
            PointStyle = t.PointStyle;
            distance = t.distance;
            TotalE = t.TotalE;
            EX = t.EX;
            EY = t.EY;
            EZ = t.EZ;
            Power = t.Power;
            ReflectionFace = t.ReflectionFace;
            Linea = t.Linea;
            Lineb = t.Lineb;
            RayIn = t.RayIn;
            DiffractionFaces = t.DiffractionFaces;
            ChildNodes = new List<Node>(t.ChildNodes);
        }
    }

    //接收球，用于判断射线是否到达接收点

    public class ReceiveBall
    {
        public double frequence;//接收机频率
        public double FrequenceWidth;//频率带宽
        public string UAN;//接收机的UAN文件
        public int RxNum;
        public string RxName;
        public Point receiver;
        public double radius;//接收球半径
        public ReceiveBall(Point final, int num, string name, double r = 100)
        {
            receiver = final;
            RxNum = num;
            radius = r;
            RxName = name;
        }
    }

    //复数类

    public class Plural
    {
        double R;
        double I;
        public double Re
        {
            get { return R; }
            set { R = value; }
        }//实部
        public double Im
        {
            get { return I; }
            set { I = value; }
        }//虚部

        //构造函数

        public Plural()
        {
            Re = Im = 0;
        }
        public Plural(double r, double i)
        {
            Re = r; Im = i;
        }
        public Plural(double r)
        {
            Re = r; Im = 0;
        }

        //取模值

        public double GetMag()
        {
            return Math.Sqrt(Math.Pow(Re, 2) + Math.Pow(Im, 2));
        }

        //取相位

        public double GetPhase()
        {
            if (Re == 0 && Im > 0)
                return Math.PI / 2;
            else if (Re == 0 && Im < 0)
                return Math.PI;
            else
                return (Math.Atan(Im / Re) * 180 / Math.PI);
        }

        //求共轭复数函数

        public Plural GetConjugate()
        {
            return new Plural(Re, -Im);
        }

        //复数表示方式转化函数

        public Plural Converse(double mag, double phase)
        {
            return new Plural(mag * Math.Cos(phase * Math.PI / 180), mag * Math.Sin(phase * Math.PI / 180));
        }

        //加减乘除函数

        static public Plural operator +(Plural one, Plural two)
        {
            return new Plural(one.Re + two.Re, one.Im + two.Im);
        }
        static public Plural operator -(Plural one, Plural two)
        {
            return new Plural(one.Re - two.Re, one.Im - two.Im);
        }
        static public Plural operator *(Plural one, Plural two)
        {
            double temp1, temp2;
            temp1 = one.Re * two.Re - one.Im * two.Im;
            temp2 = one.Im * two.Re + one.Re * two.Im;
            return new Plural(temp1, temp2);
        }
        static public Plural operator /(Plural one, Plural two)
        {
            double temp1, temp2, temp3;
            temp1 = one.Re * two.Re + one.Im * two.Im;
            temp2 = one.Im * two.Re - one.Re * two.Im;
            temp3 = Math.Pow(two.Re, 2) + Math.Pow(two.Im, 2);
            return new Plural(temp1 / temp3, temp2 / temp3);
        }
        //复数开根号运算
        public static Plural PluralSqrt(Plural p)
        {
            Plural p1 = new Plural();
            p1.Re = Math.Sqrt((Math.Sqrt(p.Re * p.Re + p.Im * p.Im) + p.Re) / 2);
            p1.Im = -Math.Sqrt((Math.Sqrt(p.Re * p.Re + p.Im * p.Im) - p.Re) / 2);
            return p1;
        }

        //复数与int型数据乘法运算
        public static Plural PluralMultiplyDouble(Plural p, double k)
        {
            Plural p1 = new Plural();
            p1.Re = p.Re * k;
            p1.Im = p.Im * k;
            return p1;
        }
    }

    //电场强度类

    public class Efield
    {
        Plural Xvertical;
        Plural Yvertical;
        Plural Zvertical;
        public Plural X
        {
            get { return Xvertical; }
            set { Xvertical = value; }
        }
        public Plural Y
        {
            get { return Yvertical; }
            set { Yvertical = value; }
        }
        public Plural Z
        {
            get { return Zvertical; }
            set { Zvertical = value; }
        }
        public Efield()
        {
            X = new Plural(0, 0);
            Y = new Plural(0, 0);
            Z = new Plural(0, 0);

        }
        public Efield(Plural x, Plural y, Plural z)
        {
            X = x; Y = y; Z = z;
        }

        public SpectVector GetTotal()
        {
            return new SpectVector(X.Re, Y.Re, Z.Re);
        }
        //求得电场的垂直分量
        public static Plural GetVerticalE(Efield e, SpectVector k, SpectVector l)  //k为射线传播方向，l为反射中的反射面的法向量或绕射中的与棱平行的向量
        {
            SpectVector n = SpectVector.VectorCrossMultiply(k, l);
            Plural p = SpectVector.VectorDotMultiply(e, n);
            return p;
        }
        //求得电场的水平分量
        public static Plural GetHorizonalE(Efield e, SpectVector k, SpectVector l)
        {
            SpectVector n = SpectVector.VectorCrossMultiply(k, l);   //入射面的法向量
            SpectVector m = SpectVector.VectorCrossMultiply(k, n);
            Plural p = SpectVector.VectorDotMultiply(e, m);
            return p;
        }
        //求电场幅值new
        public double Mag()
        {
            return Math.Sqrt(Math.Pow(Xvertical.GetMag(), 2) + Math.Pow(Yvertical.GetMag(), 2) + Math.Pow(Zvertical.GetMag(), 2));
        }
    }

    //路径节点类

    public class PathNode
    {
        public string pointstyle;
        public Point position;
        public Plural power;
        public List<Face> RorDFace;
        //public double loss;
        public Efield totalE;
        public int num;
        public double distance;
        public string name;
        public PathNode(Node node)
        {
            position = node.Position;
            power = node.Power;
            totalE = node.TotalE;
            pointstyle = node.PointStyle;
            if (node.IsEnd) num = node.RxNum;
            else if (node.PointStyle == "Tx") num = node.TxNum;
            distance = node.distance;
            name = node.NodeName;
            if (node.PointStyle == "ReflectionPoint") RorDFace = new List<Face>() { node.ReflectionFace };
            else if (node.PointStyle == "DiffractionPoint") RorDFace = node.DiffractionFaces;
        }
    }

    //路径

    public class Path
    {
        public int Txnum;
        public int Rxnum;
        public double pathloss;
        public double Delay;
        public double thetaa, phia, thetab, phib;
        public List<PathNode> node;
        public Path(List<PathNode> nodes)
        {
            node = nodes;
            Txnum = nodes[0].num;
            Rxnum = nodes[nodes.Count - 1].num;
        }
        public double GetPathLength()
        {
            double length = 0;
            for (int i = 0; i < node.Count; i++)
            {
                length += node[i].distance;
            }
            return length;
        }
    }
}
